发布于 

Wash[贪心]

Wash[贪心]

hdu 6000

集训时的一道题,做的时候靠蒙找到了最优情况,实际上是可以严格的证明的。

题解

较为复杂的贪心算法,其难度也主要是集中在选择其贪心策略的问题上,或者说是对贪心策略正确性的证明上。所以我们集中来看这道题的贪心策略。

题目给出了一个w[]数组和一个d[]数组,要求其中各取L个数,然后令其$ max( w_i + d_j )\(。所以我们的目标是找到一种组合情况,使得\)w_i+d_j$的最大值最小。

首先,对于从w[]d[]数组中取出的L个数,我们肯定是要取出最小的L个。然后,我们可以粗略的看出,当我们的w[]越小时,我们取的d[]越大越好。因此,我们可以对w[]从小到大排序,d[]从大到小排序,然后每个各自相加即可。

我们可以较为严格的证明一下: 假设我们已经按照如上顺序放好。那么,我们对于$ i,j (i < j)\(, 其一定满足\) w_i w_j , d_i d_j $,所以当我们调换顺序时,这两个数中的最大值一定会大于等于原来的最大值。并且这两个数的调换不会对其他数造成影响,所以我们明显不能调换,原来的顺序即使最佳情况。

此外,还需要注意的一点: 对于此题,由于洗衣机和干洗机都可以重复使用,所以我们刚开始需要从中取出的L个数并不仅仅是排序后取前L个,而是需要考虑一个机子使用多次的情况,所以这里最好用优先队列,一个个的取出,然后再将下一次能够使用的时间放入。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <cstdio>
#include <algorithm>
#include <queue>

using namespace std;

struct Node
{
truelong long x,base;

trueNode(long long x,long long base):x(x),base(base) {}

trueconst bool operator < (const Node &tmp) const{
truetruereturn x > tmp.x;
true}
};

long long t1[1000100],t2[1000100];
priority_queue<Node> q1,q2;

int main()
{
trueint T;
truescanf("%d",&T);

truefor (int cas = 1; cas<=T; cas++)
true{
truetrueq1 = priority_queue<Node>();
truetrueq2 = priority_queue<Node>();

truetrueint l,n,m;
truetruescanf("%d%d%d",&l,&n,&m);

truetruefor (int i = 1; i<=n; i++)
truetrue{
truetruetruelong long x;
truetruetruescanf("%lld",&x);

truetruetrueq1.push(Node(x,x));
truetrue}

truetruefor (int i = 1; i<=m; i++)
truetrue{
truetruetruelong long x;
truetruetruescanf("%lld",&x);

truetruetrueq2.push(Node(x,x));
truetrue}

truetruefor (int i = 1; i<=l; i++)
truetrue{
truetruetrueNode t = q1.top();
truetruetrueq1.pop();

truetruetruet1[i] = t.x;
truetruetruet.x += t.base;

truetruetrueq1.push(t);
truetrue}

truetruefor (int i = 1; i<=l; i++)
truetrue{
truetruetrueNode t = q2.top();
truetruetrueq2.pop();

truetruetruet2[i] = t.x;
truetruetruet.x += t.base;

truetruetrueq2.push(t);
truetrue}

truetruelong long ans = 0;
truetruefor (int i = 1; i<=l; i++)
truetruetrueans = max(ans, t1[i] + t2[l-i+1]);

truetrueprintf("Case #%d: %lld\n",cas,ans);
true}
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Songer](https://blog.songer.xyz/) 创建,使用 Stellar 作为主题。